//! Epic 14: 批量日志处理 - 验收测试
//!
//! ## 测试场景
//!
//! - AC-14.1: 批量写入缓冲区
//! - AC-14.5: 关闭完整性

mod common;

use log4r::appender::Appender;
use log4r::async_rt::{
    LogChannel, Worker, WorkerConfig, DEFAULT_BATCH_SIZE, DEFAULT_BATCH_TIMEOUT_MS,
};
use log4r::error::Log4rError;
use log4r::event::LogEvent;
use log4r::level::Level;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::{Duration, Instant};

// ============================================================================
// 测试基础设施
// ============================================================================

/// 测试用 Mock Appender - 记录写入事件和时间戳
struct TimedAppender {
    /// 记录的事件 (时间戳, 级别, 消息)
    events: Arc<Mutex<Vec<(Instant, Level, String)>>>,
    /// flush 调用次数
    flush_count: Arc<AtomicUsize>,
    /// close 调用次数
    close_count: Arc<AtomicUsize>,
    /// 每次 flush 时的事件数量快照
    flush_snapshots: Arc<Mutex<Vec<usize>>>,
}

impl TimedAppender {
    fn new() -> Self {
        Self {
            events: Arc::new(Mutex::new(Vec::new())),
            flush_count: Arc::new(AtomicUsize::new(0)),
            close_count: Arc::new(AtomicUsize::new(0)),
            flush_snapshots: Arc::new(Mutex::new(Vec::new())),
        }
    }

    fn events_clone(&self) -> Arc<Mutex<Vec<(Instant, Level, String)>>> {
        Arc::clone(&self.events)
    }

    fn flush_count_clone(&self) -> Arc<AtomicUsize> {
        Arc::clone(&self.flush_count)
    }

    fn close_count_clone(&self) -> Arc<AtomicUsize> {
        Arc::clone(&self.close_count)
    }

    fn flush_snapshots_clone(&self) -> Arc<Mutex<Vec<usize>>> {
        Arc::clone(&self.flush_snapshots)
    }
}

impl Appender for TimedAppender {
    fn write(&self, event: &LogEvent) -> Result<(), Log4rError> {
        if let Ok(mut events) = self.events.lock() {
            events.push((Instant::now(), event.level, event.message.to_string()));
        }
        Ok(())
    }

    fn flush(&self) -> Result<(), Log4rError> {
        self.flush_count.fetch_add(1, Ordering::SeqCst);
        // 记录 flush 时的事件数量
        if let Ok(events) = self.events.lock() {
            if let Ok(mut snapshots) = self.flush_snapshots.lock() {
                snapshots.push(events.len());
            }
        }
        Ok(())
    }

    fn close(&self) -> Result<(), Log4rError> {
        self.close_count.fetch_add(1, Ordering::SeqCst);
        Ok(())
    }
}

// ============================================================================
// AC-14.1: 批量写入缓冲区测试
// ============================================================================

/// T-14-P0-001: 累积 batch_size 条日志时触发批量写入 (AC-14.1.1)
#[test]
fn test_batch_size_triggers_write() {
    // GIVEN: 配置 batch_size = 10
    let channel = LogChannel::new(100);
    let sender = channel.sender();
    let mock = TimedAppender::new();
    let events_ref = mock.events_clone();
    let flush_count_ref = mock.flush_count_clone();
    let appenders: Vec<Arc<dyn Appender>> = vec![Arc::new(mock)];
    let fallback: Arc<dyn Appender> = Arc::new(TimedAppender::new());

    let config = WorkerConfig {
        batch_size: 10,
        batch_timeout_ms: 10000, // 长超时，确保不触发
    };

    let worker = Worker::start(
        channel.receiver().clone(),
        appenders,
        fallback,
        config,
        "test_app".to_string(),
    );

    // WHEN: 发送 10 条日志（达到 batch_size）
    for i in 0..10 {
        let event = LogEvent::new(Level::Info, "test", format!("msg{}", i));
        let _ = sender.send(event);
    }

    // 等待处理
    thread::sleep(Duration::from_millis(100));

    // THEN: 应触发批量写入
    let events = events_ref.lock().unwrap();
    assert_eq!(events.len(), 10, "应收到 10 条日志");

    let flush_count = flush_count_ref.load(Ordering::SeqCst);
    assert!(flush_count >= 1, "flush 应至少被调用 1 次");

    // 清理
    drop(sender);
    let _ = worker.shutdown();
}

/// T-14-P0-003: 未达到 batch_size 时，只有在 shutdown 时才处理 (AC-14.1.2)
#[test]
fn test_batch_not_trigger_below_size() {
    // GIVEN: 配置 batch_size = 100
    let channel = LogChannel::new(100);
    let sender = channel.sender();
    let mock = TimedAppender::new();
    let events_ref = mock.events_clone();
    let flush_snapshots_ref = mock.flush_snapshots_clone();
    let appenders: Vec<Arc<dyn Appender>> = vec![Arc::new(mock)];
    let fallback: Arc<dyn Appender> = Arc::new(TimedAppender::new());

    let config = WorkerConfig {
        batch_size: 100,
        batch_timeout_ms: 10000, // 长超时
    };

    let worker = Worker::start(
        channel.receiver().clone(),
        appenders,
        fallback,
        config,
        "test_app".to_string(),
    );

    // WHEN: 发送 50 条日志（未达到 batch_size）
    for i in 0..50 {
        let event = LogEvent::new(Level::Info, "test", format!("msg{}", i));
        let _ = sender.send(event);
    }

    // 等待事件进入队列
    thread::sleep(Duration::from_millis(50));

    // AND: 调用 shutdown（此时应处理剩余批次）
    drop(sender);
    let _ = worker.shutdown();

    // THEN: shutdown 后应处理所有 50 条事件
    let events = events_ref.lock().unwrap();
    assert_eq!(events.len(), 50, "shutdown 后应处理所有剩余事件");

    // 验证：只有一次 flush（shutdown 时的批次）
    let snapshots = flush_snapshots_ref.lock().unwrap();
    assert!(!snapshots.is_empty(), "应至少有一次 flush");
}

// ============================================================================
// AC-14.2: 超时刷新测试
// ============================================================================

/// T-14-P0-004: 超时触发刷新（批次非空）(AC-14.2.1 #1)
#[test]
fn test_timeout_triggers_flush_when_batch_not_empty() {
    // GIVEN: 配置 batch_size = 100, batch_timeout_ms = 50
    let channel = LogChannel::new(100);
    let sender = channel.sender();
    let mock = TimedAppender::new();
    let events_ref = mock.events_clone();
    let flush_count_ref = mock.flush_count_clone();
    let appenders: Vec<Arc<dyn Appender>> = vec![Arc::new(mock)];
    let fallback: Arc<dyn Appender> = Arc::new(TimedAppender::new());

    let config = WorkerConfig {
        batch_size: 100,      // 大批量，确保不会因大小触发
        batch_timeout_ms: 50, // 短超时
    };

    let worker = Worker::start(
        channel.receiver().clone(),
        appenders,
        fallback,
        config,
        "test_app".to_string(),
    );

    // WHEN: 发送 10 条日志（远小于 batch_size）
    for i in 0..10 {
        let event = LogEvent::new(Level::Info, "test", format!("timeout_msg{}", i));
        let _ = sender.send(event);
    }

    // 等待超时触发（50ms + 缓冲）
    thread::sleep(Duration::from_millis(150));

    // THEN: 超时应触发刷新
    let events = events_ref.lock().unwrap();
    assert_eq!(events.len(), 10, "超时后应刷新所有 10 条日志");

    let flush_count = flush_count_ref.load(Ordering::SeqCst);
    assert!(flush_count >= 1, "超时应触发至少 1 次 flush");

    // 清理
    drop(sender);
    let _ = worker.shutdown();
}

/// T-14-P0-005: 超时不触发（批次为空）(AC-14.2.1 #2)
#[test]
fn test_timeout_no_flush_when_batch_empty() {
    // GIVEN: 配置 batch_timeout_ms = 50
    let channel = LogChannel::new(100);
    let sender = channel.sender();
    let mock = TimedAppender::new();
    let events_ref = mock.events_clone();
    let flush_count_ref = mock.flush_count_clone();
    let appenders: Vec<Arc<dyn Appender>> = vec![Arc::new(mock)];
    let fallback: Arc<dyn Appender> = Arc::new(TimedAppender::new());

    let config = WorkerConfig {
        batch_size: 100,
        batch_timeout_ms: 50,
    };

    let worker = Worker::start(
        channel.receiver().clone(),
        appenders,
        fallback,
        config,
        "test_app".to_string(),
    );

    // WHEN: 不发送任何日志，等待超时
    thread::sleep(Duration::from_millis(150));

    // THEN: 批次为空，不应触发 flush
    let events = events_ref.lock().unwrap();
    assert_eq!(events.len(), 0, "批次为空时不应有事件");

    // 注意：空批次超时不会调用 flush
    // 清理
    drop(sender);
    let _ = worker.shutdown();

    // shutdown 后可能有 flush 调用，但在超时期间不应有
    let flush_count = flush_count_ref.load(Ordering::SeqCst);
    // flush_count 可能为 0 或 1（shutdown 时的 drain_queue 可能调用）
    assert!(flush_count <= 1, "空批次超时不应触发额外 flush");
}

/// T-14-P0-006: 超时触发刷新，即使未达到 batch_size (AC-14.2.2 #3)
#[test]
fn test_timeout_flushes_partial_batch() {
    // GIVEN: 配置 batch_size = 100, batch_timeout_ms = 50
    let channel = LogChannel::new(100);
    let sender = channel.sender();
    let mock = TimedAppender::new();
    let events_ref = mock.events_clone();
    let flush_snapshots_ref = mock.flush_snapshots_clone();
    let appenders: Vec<Arc<dyn Appender>> = vec![Arc::new(mock)];
    let fallback: Arc<dyn Appender> = Arc::new(TimedAppender::new());

    let config = WorkerConfig {
        batch_size: 100,
        batch_timeout_ms: 50,
    };

    let worker = Worker::start(
        channel.receiver().clone(),
        appenders,
        fallback,
        config,
        "test_app".to_string(),
    );

    // WHEN: 发送 50 条日志（batch_size 的一半）
    for i in 0..50 {
        let event = LogEvent::new(Level::Info, "test", format!("partial_msg{}", i));
        let _ = sender.send(event);
    }

    // 等待超时触发
    thread::sleep(Duration::from_millis(150));

    // THEN: 超时应触发刷新，即使只有 50 条
    let events = events_ref.lock().unwrap();
    assert_eq!(events.len(), 50, "超时应刷新部分批次");

    let snapshots = flush_snapshots_ref.lock().unwrap();
    assert!(!snapshots.is_empty(), "应有 flush 快照");
    assert_eq!(snapshots[0], 50, "第一次 flush 时应有 50 条事件");

    // 清理
    drop(sender);
    let _ = worker.shutdown();
}

/// T-14-P0-007: 批量大小触发优先于超时 (AC-14.2.2 #4)
#[test]
fn test_batch_size_triggers_before_timeout() {
    // GIVEN: 配置 batch_size = 10, batch_timeout_ms = 1000（长超时）
    let channel = LogChannel::new(100);
    let sender = channel.sender();
    let mock = TimedAppender::new();
    let events_ref = mock.events_clone();
    let flush_count_ref = mock.flush_count_clone();
    let appenders: Vec<Arc<dyn Appender>> = vec![Arc::new(mock)];
    let fallback: Arc<dyn Appender> = Arc::new(TimedAppender::new());

    let config = WorkerConfig {
        batch_size: 10,
        batch_timeout_ms: 1000, // 长超时
    };

    let start = Instant::now();

    let worker = Worker::start(
        channel.receiver().clone(),
        appenders,
        fallback,
        config,
        "test_app".to_string(),
    );

    // WHEN: 快速发送 10 条日志（达到 batch_size）
    for i in 0..10 {
        let event = LogEvent::new(Level::Info, "test", format!("batch_msg{}", i));
        let _ = sender.send(event);
    }

    // 等待处理（但远小于超时时间）
    thread::sleep(Duration::from_millis(100));

    // THEN: 应在超时前触发刷新
    let elapsed = start.elapsed();
    assert!(elapsed < Duration::from_millis(500), "应在超时前触发刷新");

    let events = events_ref.lock().unwrap();
    assert_eq!(events.len(), 10, "应收到 10 条日志");

    let flush_count = flush_count_ref.load(Ordering::SeqCst);
    assert!(flush_count >= 1, "批量大小应触发 flush");

    // 清理
    drop(sender);
    let _ = worker.shutdown();
}

/// T-14-P0-008: 超时计时器在刷新后重置 (AC-14.2.3 #5)
#[test]
fn test_timeout_timer_resets_after_flush() {
    // GIVEN: 配置 batch_timeout_ms = 80
    let channel = LogChannel::new(100);
    let sender = channel.sender();
    let mock = TimedAppender::new();
    let events_ref = mock.events_clone();
    let flush_count_ref = mock.flush_count_clone();
    let appenders: Vec<Arc<dyn Appender>> = vec![Arc::new(mock)];
    let fallback: Arc<dyn Appender> = Arc::new(TimedAppender::new());

    let config = WorkerConfig {
        batch_size: 100,
        batch_timeout_ms: 80,
    };

    let worker = Worker::start(
        channel.receiver().clone(),
        appenders,
        fallback,
        config,
        "test_app".to_string(),
    );

    // WHEN: 发送第一批日志
    for i in 0..5 {
        let event = LogEvent::new(Level::Info, "test", format!("batch1_msg{}", i));
        let _ = sender.send(event);
    }

    // 等待第一次超时触发
    thread::sleep(Duration::from_millis(150));

    // 验证第一批已刷新
    {
        let events = events_ref.lock().unwrap();
        assert_eq!(events.len(), 5, "第一批应已刷新");
    }

    // AND: 发送第二批日志
    for i in 0..3 {
        let event = LogEvent::new(Level::Info, "test", format!("batch2_msg{}", i));
        let _ = sender.send(event);
    }

    // 等待第二次超时触发
    thread::sleep(Duration::from_millis(150));

    // THEN: 第二批也应被刷新（计时器已重置）
    let events = events_ref.lock().unwrap();
    assert_eq!(events.len(), 8, "两批共 8 条日志应都被刷新");

    let flush_count = flush_count_ref.load(Ordering::SeqCst);
    assert!(flush_count >= 2, "应至少有 2 次 flush（每批一次）");

    // 清理
    drop(sender);
    let _ = worker.shutdown();
}

// ============================================================================
// AC-14.5: 关闭完整性测试
// ============================================================================

/// T-14-P0-009: shutdown 时处理当前批次 (AC-14.5.1)
#[test]
fn test_shutdown_processes_current_batch() {
    // GIVEN: 配置 batch_size = 100
    let channel = LogChannel::new(100);
    let sender = channel.sender();
    let mock = TimedAppender::new();
    let events_ref = mock.events_clone();
    let close_count_ref = mock.close_count_clone();
    let appenders: Vec<Arc<dyn Appender>> = vec![Arc::new(mock)];
    let fallback: Arc<dyn Appender> = Arc::new(TimedAppender::new());

    let config = WorkerConfig {
        batch_size: 100,
        batch_timeout_ms: 10000, // 长超时
    };

    let worker = Worker::start(
        channel.receiver().clone(),
        appenders,
        fallback,
        config,
        "test_app".to_string(),
    );

    // WHEN: 发送 30 条日志（未达到 batch_size）
    for i in 0..30 {
        let event = LogEvent::new(Level::Info, "test", format!("shutdown_msg{}", i));
        let _ = sender.send(event);
    }

    // 等待事件进入队列
    thread::sleep(Duration::from_millis(50));

    // AND: 调用 shutdown
    drop(sender);
    let result = worker.shutdown();

    // THEN: 关闭应成功，所有 30 条日志应被处理
    assert!(result.is_ok(), "shutdown 应成功");

    let events = events_ref.lock().unwrap();
    assert_eq!(events.len(), 30, "shutdown 时应处理当前批次中的所有日志");

    let close_count = close_count_ref.load(Ordering::SeqCst);
    assert_eq!(close_count, 1, "close 应被调用");
}

/// T-14-P0-010: shutdown 时清空队列所有日志 (AC-14.5.2)
#[test]
fn test_shutdown_drains_queue_completely() {
    // GIVEN: 配置 batch_size = 10
    let channel = LogChannel::new(200);
    let sender = channel.sender();
    let mock = TimedAppender::new();
    let events_ref = mock.events_clone();
    let appenders: Vec<Arc<dyn Appender>> = vec![Arc::new(mock)];
    let fallback: Arc<dyn Appender> = Arc::new(TimedAppender::new());

    let config = WorkerConfig {
        batch_size: 10,
        batch_timeout_ms: 10000, // 长超时
    };

    let worker = Worker::start(
        channel.receiver().clone(),
        appenders,
        fallback,
        config,
        "test_app".to_string(),
    );

    // WHEN: 快速发送 55 条日志
    for i in 0..55 {
        let event = LogEvent::new(Level::Info, "test", format!("drain_msg{}", i));
        let _ = sender.send(event);
    }

    // 立即关闭
    drop(sender);
    let result = worker.shutdown();

    // THEN: 关闭应成功，所有 55 条日志应被处理
    assert!(result.is_ok(), "shutdown 应成功");

    let events = events_ref.lock().unwrap();
    assert_eq!(events.len(), 55, "shutdown 时应清空队列中所有日志");
}

// ============================================================================
// 配置测试
// ============================================================================

/// 测试默认配置值
#[test]
fn test_default_config_values() {
    let config = WorkerConfig::default();
    assert_eq!(config.batch_size, DEFAULT_BATCH_SIZE);
    assert_eq!(config.batch_size, 100);
    assert_eq!(config.batch_timeout_ms, DEFAULT_BATCH_TIMEOUT_MS);
    assert_eq!(config.batch_timeout_ms, 100);
}

/// 测试自定义配置
#[test]
fn test_custom_config() {
    let config = WorkerConfig {
        batch_size: 50,
        batch_timeout_ms: 200,
    };
    assert_eq!(config.batch_size, 50);
    assert_eq!(config.batch_timeout_ms, 200);
}

// ============================================================================
// AC-14.3: FATAL 立即刷新测试
// ============================================================================

/// IT-14.3-001: FATAL 在高负载场景下的立即刷新 (AC-14.3.1, AC-14.3.3)
#[test]
fn test_fatal_immediate_flush_under_high_load() {
    // GIVEN: 配置大批量大小和长超时
    let channel = LogChannel::new(500);
    let sender = channel.sender();
    let mock = TimedAppender::new();
    let events_ref = mock.events_clone();
    let flush_count_ref = mock.flush_count_clone();
    let appenders: Vec<Arc<dyn Appender>> = vec![Arc::new(mock)];
    let fallback: Arc<dyn Appender> = Arc::new(TimedAppender::new());

    let config = WorkerConfig {
        batch_size: 200,
        batch_timeout_ms: 10000, // 长超时
    };

    let worker = Worker::start(
        channel.receiver().clone(),
        appenders,
        fallback,
        config,
        "test_app".to_string(),
    );

    // WHEN: 高负载发送日志，中间穿插 FATAL
    // 发送 100 条 INFO
    for i in 0..100 {
        let event = LogEvent::new(Level::Info, "test", format!("load_info_{}", i));
        let _ = sender.send(event);
    }

    // 发送 FATAL
    let fatal_event = LogEvent::new(Level::Fatal, "test", "critical_error");
    let _ = sender.send(fatal_event);

    // 继续发送 50 条 INFO
    for i in 0..50 {
        let event = LogEvent::new(Level::Info, "test", format!("after_fatal_{}", i));
        let _ = sender.send(event);
    }

    // 等待处理
    thread::sleep(Duration::from_millis(200));

    // THEN: FATAL 应触发立即刷新
    let events = events_ref.lock().unwrap();
    // 至少应包含 FATAL 之前的日志 + FATAL
    assert!(
        events.len() >= 101,
        "FATAL 应触发立即刷新，至少包含 101 条日志"
    );

    // 验证 FATAL 日志存在
    let has_fatal = events
        .iter()
        .any(|(_, level, msg)| *level == Level::Fatal && msg.contains("critical_error"));
    assert!(has_fatal, "应包含 FATAL 日志");

    // flush 应被调用
    let flush_count = flush_count_ref.load(Ordering::SeqCst);
    assert!(flush_count >= 1, "FATAL 应触发 flush");

    // 清理
    drop(sender);
    let _ = worker.shutdown();
}

/// IT-14.3-002: 连续 FATAL 日志的处理 (AC-14.3.1, AC-14.3.2)
#[test]
fn test_consecutive_fatal_logs() {
    // GIVEN: 配置大批量大小
    let channel = LogChannel::new(200);
    let sender = channel.sender();
    let mock = TimedAppender::new();
    let events_ref = mock.events_clone();
    let flush_count_ref = mock.flush_count_clone();
    let appenders: Vec<Arc<dyn Appender>> = vec![Arc::new(mock)];
    let fallback: Arc<dyn Appender> = Arc::new(TimedAppender::new());

    let config = WorkerConfig {
        batch_size: 100,
        batch_timeout_ms: 10000,
    };

    let worker = Worker::start(
        channel.receiver().clone(),
        appenders,
        fallback,
        config,
        "test_app".to_string(),
    );

    // WHEN: 发送多条连续 FATAL 日志
    for i in 0..5 {
        // 发送一些 INFO
        for j in 0..10 {
            let event = LogEvent::new(Level::Info, "test", format!("info_{}_{}", i, j));
            let _ = sender.send(event);
        }
        // 发送 FATAL
        let fatal_event = LogEvent::new(Level::Fatal, "test", format!("fatal_{}", i));
        let _ = sender.send(fatal_event);
    }

    // 等待处理
    thread::sleep(Duration::from_millis(300));

    // THEN: 所有日志应被处理，每个 FATAL 都应触发刷新
    let events = events_ref.lock().unwrap();
    // 5 * 10 INFO + 5 FATAL = 55 条
    assert_eq!(events.len(), 55, "所有 55 条日志应被处理");

    // 验证所有 FATAL 日志存在
    let fatal_count = events
        .iter()
        .filter(|(_, level, _)| *level == Level::Fatal)
        .count();
    assert_eq!(fatal_count, 5, "应有 5 条 FATAL 日志");

    // 每个 FATAL 应触发一次 flush
    let flush_count = flush_count_ref.load(Ordering::SeqCst);
    assert!(flush_count >= 5, "每个 FATAL 应触发 flush，至少 5 次");

    // 清理
    drop(sender);
    let _ = worker.shutdown();
}

// ============================================================================
// AC-14.4: 批量配置测试 (Story 14.4)
// ============================================================================

/// IT-14.4-001: 测试配置文件初始化使用自定义批量参数 (AC-14.4.1, AC-14.4.2, AC-14.4.5)
#[test]
fn test_config_file_batch_params() {
    use log4r::config::Log4rConfig;

    // GIVEN: 包含自定义批量参数的配置
    let toml_str = r#"
level = "info"
app_name = "batch_test"

[async]
enabled = true
queue_size = 5000
batch_size = 50
batch_timeout_ms = 200
"#;

    // WHEN: 解析配置
    let config: Log4rConfig = toml::from_str(toml_str).unwrap();

    // THEN: 批量参数应正确解析
    assert_eq!(config.async_config.batch_size, 50, "batch_size 应为 50");
    assert_eq!(
        config.async_config.batch_timeout_ms, 200,
        "batch_timeout_ms 应为 200"
    );

    // AND: 验证配置有效
    assert!(config.async_config.validate().is_ok(), "配置应验证通过");
}

/// IT-14.4-002: 测试 Builder 批量配置方法存在且可链式调用 (AC-14.4.3, AC-14.4.5)
#[test]
fn test_builder_batch_params() {
    use log4r::Log4rBuilder;

    // GIVEN/WHEN: 使用 Builder 设置批量参数（链式调用）
    let _builder = Log4rBuilder::new()
        .with_batch_size(50)
        .with_batch_timeout(200);

    // THEN: 编译通过即验证方法存在且可链式调用
    // 注意：Builder 字段是私有的，无法直接验证值
    // 实际验证通过 IT-14.4-006 和 IT-14.4-007 测试 Worker 行为
}

/// IT-14.4-003: 测试配置默认值 (AC-14.4.1 #2, AC-14.4.2 #4)
#[test]
fn test_config_batch_defaults() {
    use log4r::config::AsyncConfig;

    // GIVEN: 不包含批量参数的配置
    let toml_str = r#"
enabled = true
queue_size = 10000
"#;

    // WHEN: 解析配置
    let config: AsyncConfig = toml::from_str(toml_str).unwrap();

    // THEN: 应使用默认值
    assert_eq!(config.batch_size, 100, "batch_size 默认应为 100");
    assert_eq!(
        config.batch_timeout_ms, 100,
        "batch_timeout_ms 默认应为 100"
    );
}

/// IT-14.4-004: 测试 batch_size = 0 验证失败 (AC-14.4.4 #7)
#[test]
fn test_config_batch_size_zero_validation() {
    use log4r::config::AsyncConfig;

    // GIVEN: batch_size 为 0 的配置
    let config = AsyncConfig {
        batch_size: 0,
        ..Default::default()
    };

    // WHEN: 验证配置
    let result = config.validate();

    // THEN: 应返回错误，错误信息包含 "batch_size"
    assert!(result.is_err(), "batch_size = 0 应验证失败");
    let err_msg = result.unwrap_err().to_string();
    assert!(
        err_msg.contains("batch_size"),
        "错误信息应包含 'batch_size'"
    );
}

/// IT-14.4-005: 测试 batch_timeout_ms = 0 验证失败 (AC-14.4.4 #8)
#[test]
fn test_config_batch_timeout_zero_validation() {
    use log4r::config::AsyncConfig;

    // GIVEN: batch_timeout_ms 为 0 的配置
    let config = AsyncConfig {
        batch_timeout_ms: 0,
        ..Default::default()
    };

    // WHEN: 验证配置
    let result = config.validate();

    // THEN: 应返回错误，错误信息包含 "batch_timeout_ms"
    assert!(result.is_err(), "batch_timeout_ms = 0 应验证失败");
    let err_msg = result.unwrap_err().to_string();
    assert!(
        err_msg.contains("batch_timeout_ms"),
        "错误信息应包含 'batch_timeout_ms'"
    );
}

/// IT-14.4-006: 测试自定义批量配置传递到 Worker (AC-14.4.5 #9)
#[test]
fn test_custom_batch_config_passed_to_worker() {
    // GIVEN: 自定义批量配置
    let channel = LogChannel::new(100);
    let sender = channel.sender();
    let mock = TimedAppender::new();
    let events_ref = mock.events_clone();
    let flush_count_ref = mock.flush_count_clone();
    let appenders: Vec<Arc<dyn Appender>> = vec![Arc::new(mock)];
    let fallback: Arc<dyn Appender> = Arc::new(TimedAppender::new());

    // 使用自定义配置：batch_size = 5
    let config = WorkerConfig {
        batch_size: 5,
        batch_timeout_ms: 10000, // 长超时
    };

    let worker = Worker::start(
        channel.receiver().clone(),
        appenders,
        fallback,
        config,
        "test_app".to_string(),
    );

    // WHEN: 发送 5 条日志（达到自定义 batch_size）
    for i in 0..5 {
        let event = LogEvent::new(Level::Info, "test", format!("custom_batch_{}", i));
        let _ = sender.send(event);
    }

    // 等待处理
    thread::sleep(Duration::from_millis(100));

    // THEN: 应触发批量写入（因为达到自定义 batch_size = 5）
    let events = events_ref.lock().unwrap();
    assert_eq!(events.len(), 5, "应收到 5 条日志");

    let flush_count = flush_count_ref.load(Ordering::SeqCst);
    assert!(flush_count >= 1, "自定义 batch_size 应触发 flush");

    // 清理
    drop(sender);
    let _ = worker.shutdown();
}

/// IT-14.4-007: 测试自定义超时配置传递到 Worker (AC-14.4.5 #9)
#[test]
fn test_custom_timeout_config_passed_to_worker() {
    // GIVEN: 自定义超时配置
    let channel = LogChannel::new(100);
    let sender = channel.sender();
    let mock = TimedAppender::new();
    let events_ref = mock.events_clone();
    let flush_count_ref = mock.flush_count_clone();
    let appenders: Vec<Arc<dyn Appender>> = vec![Arc::new(mock)];
    let fallback: Arc<dyn Appender> = Arc::new(TimedAppender::new());

    // 使用自定义配置：batch_timeout_ms = 30
    let config = WorkerConfig {
        batch_size: 100, // 大批量，确保不会因大小触发
        batch_timeout_ms: 30,
    };

    let worker = Worker::start(
        channel.receiver().clone(),
        appenders,
        fallback,
        config,
        "test_app".to_string(),
    );

    // WHEN: 发送 3 条日志（远小于 batch_size）
    for i in 0..3 {
        let event = LogEvent::new(Level::Info, "test", format!("timeout_test_{}", i));
        let _ = sender.send(event);
    }

    // 等待自定义超时触发（30ms + 缓冲）
    thread::sleep(Duration::from_millis(100));

    // THEN: 自定义超时应触发刷新
    let events = events_ref.lock().unwrap();
    assert_eq!(events.len(), 3, "自定义超时后应刷新所有 3 条日志");

    let flush_count = flush_count_ref.load(Ordering::SeqCst);
    assert!(flush_count >= 1, "自定义超时应触发 flush");

    // 清理
    drop(sender);
    let _ = worker.shutdown();
}

// ============================================================================
// 边界值测试 (P2)
// ============================================================================

/// T-14-P2-001: batch_size=1 边界值（退化为逐条写入）
///
/// 验证当 batch_size=1 时，每条日志都会立即触发写入，
/// 行为退化为逐条写入模式。
#[test]
fn test_batch_size_one_degrades_to_single_write() {
    // GIVEN: 配置 batch_size = 1
    let channel = LogChannel::new(100);
    let sender = channel.sender();
    let mock = TimedAppender::new();
    let events_ref = mock.events_clone();
    let flush_count_ref = mock.flush_count_clone();
    let flush_snapshots_ref = mock.flush_snapshots_clone();
    let appenders: Vec<Arc<dyn Appender>> = vec![Arc::new(mock)];
    let fallback: Arc<dyn Appender> = Arc::new(TimedAppender::new());

    let config = WorkerConfig {
        batch_size: 1,           // 边界值：每条日志立即写入
        batch_timeout_ms: 10000, // 长超时，确保不触发
    };

    let worker = Worker::start(
        channel.receiver().clone(),
        appenders,
        fallback,
        config,
        "test_app".to_string(),
    );

    // WHEN: 发送 5 条日志
    for i in 0..5 {
        let event = LogEvent::new(Level::Info, "test", format!("single_msg{}", i));
        let _ = sender.send(event);
    }

    // 等待处理
    thread::sleep(Duration::from_millis(150));

    // THEN: 每条日志应立即写入
    let events = events_ref.lock().unwrap();
    assert_eq!(events.len(), 5, "应收到 5 条日志");

    // 验证: flush 应被调用多次（每条日志一次）
    let flush_count = flush_count_ref.load(Ordering::SeqCst);
    assert!(
        flush_count >= 5,
        "batch_size=1 时，flush 应至少被调用 5 次，实际: {}",
        flush_count
    );

    // 验证: 每次 flush 时只有 1 条新增日志
    let snapshots = flush_snapshots_ref.lock().unwrap();
    if snapshots.len() >= 5 {
        // 检查每次 flush 的增量
        for i in 1..5 {
            let delta = snapshots[i] - snapshots[i - 1];
            assert_eq!(delta, 1, "每次 flush 应只增加 1 条日志");
        }
    }

    // 清理
    drop(sender);
    let _ = worker.shutdown();
}

/// T-14-P2-002: batch_size=1000 边界值（最大推荐值）
///
/// 验证大批量配置正常工作，不会导致内存问题。
#[test]
fn test_batch_size_large_value() {
    // GIVEN: 配置 batch_size = 1000（最大推荐值）
    let channel = LogChannel::new(2000);
    let sender = channel.sender();
    let mock = TimedAppender::new();
    let events_ref = mock.events_clone();
    let flush_count_ref = mock.flush_count_clone();
    let appenders: Vec<Arc<dyn Appender>> = vec![Arc::new(mock)];
    let fallback: Arc<dyn Appender> = Arc::new(TimedAppender::new());

    let config = WorkerConfig {
        batch_size: 1000,
        batch_timeout_ms: 10000, // 长超时
    };

    let worker = Worker::start(
        channel.receiver().clone(),
        appenders,
        fallback,
        config,
        "test_app".to_string(),
    );

    // WHEN: 发送 1000 条日志（达到 batch_size）
    for i in 0..1000 {
        let event = LogEvent::new(Level::Info, "test", format!("large_batch_msg{}", i));
        let _ = sender.send(event);
    }

    // 等待处理
    thread::sleep(Duration::from_millis(200));

    // THEN: 应触发一次批量写入
    let events = events_ref.lock().unwrap();
    assert_eq!(events.len(), 1000, "应收到 1000 条日志");

    let flush_count = flush_count_ref.load(Ordering::SeqCst);
    assert!(flush_count >= 1, "大批量应触发 flush");

    // 清理
    drop(sender);
    let _ = worker.shutdown();
}

/// T-14-P2-003: batch_timeout_ms=1 边界值（最小有效超时）
///
/// 验证最小超时值（1ms）正常工作。
/// 注意：batch_timeout_ms=0 会被配置验证拒绝。
#[test]
fn test_batch_timeout_minimum_value() {
    // GIVEN: 配置 batch_timeout_ms = 1（最小有效值）
    let channel = LogChannel::new(100);
    let sender = channel.sender();
    let mock = TimedAppender::new();
    let events_ref = mock.events_clone();
    let flush_count_ref = mock.flush_count_clone();
    let appenders: Vec<Arc<dyn Appender>> = vec![Arc::new(mock)];
    let fallback: Arc<dyn Appender> = Arc::new(TimedAppender::new());

    let config = WorkerConfig {
        batch_size: 100,     // 大批量，确保不会因大小触发
        batch_timeout_ms: 1, // 最小有效超时
    };

    let worker = Worker::start(
        channel.receiver().clone(),
        appenders,
        fallback,
        config,
        "test_app".to_string(),
    );

    // WHEN: 发送 1 条日志
    let event = LogEvent::new(Level::Info, "test", "min_timeout_msg");
    let _ = sender.send(event);

    // 等待超时触发（1ms + 缓冲）
    thread::sleep(Duration::from_millis(50));

    // THEN: 最小超时应触发刷新
    let events = events_ref.lock().unwrap();
    assert_eq!(events.len(), 1, "最小超时后应刷新日志");

    let flush_count = flush_count_ref.load(Ordering::SeqCst);
    assert!(flush_count >= 1, "最小超时应触发 flush");

    // 清理
    drop(sender);
    let _ = worker.shutdown();
}

/// T-14-P2-004: batch_timeout_ms=1000 边界值（最大推荐值）
///
/// 验证长超时配置正常工作。
#[test]
fn test_batch_timeout_large_value() {
    // GIVEN: 配置 batch_timeout_ms = 1000（最大推荐值）
    let channel = LogChannel::new(100);
    let sender = channel.sender();
    let mock = TimedAppender::new();
    let events_ref = mock.events_clone();
    let flush_count_ref = mock.flush_count_clone();
    let appenders: Vec<Arc<dyn Appender>> = vec![Arc::new(mock)];
    let fallback: Arc<dyn Appender> = Arc::new(TimedAppender::new());

    let config = WorkerConfig {
        batch_size: 10,         // 小批量
        batch_timeout_ms: 1000, // 长超时
    };

    let worker = Worker::start(
        channel.receiver().clone(),
        appenders,
        fallback,
        config,
        "test_app".to_string(),
    );

    // WHEN: 发送 10 条日志（达到 batch_size）
    for i in 0..10 {
        let event = LogEvent::new(Level::Info, "test", format!("long_timeout_msg{}", i));
        let _ = sender.send(event);
    }

    // 等待处理（应在超时前因 batch_size 触发）
    thread::sleep(Duration::from_millis(100));

    // THEN: 应因 batch_size 触发写入，而非超时
    let events = events_ref.lock().unwrap();
    assert_eq!(events.len(), 10, "应收到 10 条日志");

    let flush_count = flush_count_ref.load(Ordering::SeqCst);
    assert!(flush_count >= 1, "batch_size 应触发 flush");

    // 清理
    drop(sender);
    let _ = worker.shutdown();
}

// ============================================================================
// 高并发测试 (P0)
// ============================================================================

/// T-14-P0-012: 高并发日志写入不丢失
///
/// 验证在高并发场景下，批量处理不会丢失任何日志。
#[test]
fn test_high_concurrency_no_log_loss() {
    use std::sync::atomic::AtomicUsize;

    // GIVEN: 配置中等批量大小
    let channel = LogChannel::new(10000);
    let sender = channel.sender();
    let mock = TimedAppender::new();
    let events_ref = mock.events_clone();
    let appenders: Vec<Arc<dyn Appender>> = vec![Arc::new(mock)];
    let fallback: Arc<dyn Appender> = Arc::new(TimedAppender::new());

    let config = WorkerConfig {
        batch_size: 50,
        batch_timeout_ms: 50,
    };

    let worker = Worker::start(
        channel.receiver().clone(),
        appenders,
        fallback,
        config,
        "test_app".to_string(),
    );

    // WHEN: 多线程并发发送日志
    let total_logs = Arc::new(AtomicUsize::new(0));
    let num_threads = 4;
    let logs_per_thread = 250;

    let handles: Vec<_> = (0..num_threads)
        .map(|t| {
            let sender = sender.clone();
            let total = Arc::clone(&total_logs);
            thread::spawn(move || {
                for i in 0..logs_per_thread {
                    let event =
                        LogEvent::new(Level::Info, "test", format!("concurrent_t{}_msg{}", t, i));
                    if sender.send(event).is_ok() {
                        total.fetch_add(1, Ordering::SeqCst);
                    }
                }
            })
        })
        .collect();

    // 等待所有发送线程完成
    for h in handles {
        let _ = h.join();
    }

    // 等待处理完成
    thread::sleep(Duration::from_millis(500));

    // 关闭 Worker
    drop(sender);
    let _ = worker.shutdown();

    // THEN: 所有日志应被处理，无丢失
    let events = events_ref.lock().unwrap();
    let sent_count = total_logs.load(Ordering::SeqCst);
    assert_eq!(
        events.len(),
        sent_count,
        "高并发场景下不应丢失日志: 发送 {} 条，收到 {} 条",
        sent_count,
        events.len()
    );
}
